package com.qzsoft.zhjd.common.utils;


import com.qzsoft.zhjd.common.model.DuctilityFinalResult;
import com.qzsoft.zhjd.common.model.DuctilityRealTimeData;

/**
 * 云检科技（北京申克路业仪器有限公司）
 * 延度仪数据解析器
 * 负责解析16进制格式的延度仪数据
 */
public class DuctilityYjkjDataParserUtils {

    // 帧头字节
    private static final byte[] FRAME_HEADER = {(byte) 0xFA, (byte) 0xFB, (byte) 0xFC};
    // 试验实时数据标识
    private static final byte REAL_TIME_DATA = (byte) 0xA4;
    // 试验最终结果标识
    private static final byte FINAL_RESULT_DATA = (byte) 0xA7;

    /**
     * 解析16进制字符串格式的延度仪数据
     * @param hexString 16进制字符串，支持空格分隔或连续格式
     * @return 解析后的数据对象，可能是DuctilityRealTimeData或DuctilityFinalResult
     * @throws IllegalArgumentException 当数据格式错误时抛出异常
     */
    public static Object parse(String hexString) {
        // 移除字符串中的空格并转换为大写
        String cleanHex = hexString.replaceAll("\\s+", "").toUpperCase();

        // 验证字符串长度是否为偶数
        if (cleanHex.length() % 2 != 0) {
            throw new IllegalArgumentException("无效的16进制字符串长度");
        }

        // 将16进制字符串转换为字节数组
        byte[] data = hexStringToByteArray(cleanHex);

        // 验证数据基本结构
        validateBasicStructure(data);

        // 验证帧头
        validateFrameHeader(data);

        // 计算并验证校验和
        validateChecksum(data);

        // 根据数据类型进行解析
        byte dataType = data[4];
        if (dataType == REAL_TIME_DATA) {
            return parseRealTimeData(data);
        } else if (dataType == FINAL_RESULT_DATA) {
            return parseFinalResult(data);
        } else {
            throw new IllegalArgumentException("未知的数据类型标识: 0x" + String.format("%02X", dataType));
        }
    }

    /**
     * 将16进制字符串转换为字节数组
     */
    private static byte[] hexStringToByteArray(String hexString) {
        int len = hexString.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
                    + Character.digit(hexString.charAt(i + 1), 16));
        }
        return data;
    }

    /**
     * 验证数据基本结构
     */
    private static void validateBasicStructure(byte[] data) {
        if (data.length < 7) {
            throw new IllegalArgumentException("数据长度不足，至少需要7个字节");
        }
    }

    /**
     * 验证帧头
     */
    private static void validateFrameHeader(byte[] data) {
        for (int i = 0; i < FRAME_HEADER.length; i++) {
            if (data[i] != FRAME_HEADER[i]) {
                throw new IllegalArgumentException("无效的帧头");
            }
        }
    }

    /**
     * 计算并验证校验和
     */
    private static void validateChecksum(byte[] data) {
        // 数据长度字节（第4个字节）
        int dataLength = data[3] & 0xFF;

        // 计算校验和（从帧头到校验和之前的所有字节）
        int calculatedChecksum = 0;
        for (int i = 0; i < data.length - 1; i++) {
            calculatedChecksum += data[i] & 0xFF;
        }
        calculatedChecksum &= 0xFF; // 保留低8位

        // 实际的校验和（最后一个字节）
        int actualChecksum = data[data.length - 1] & 0xFF;

        if (calculatedChecksum != actualChecksum) {
            throw new IllegalArgumentException(String.format(
                    "校验和错误: 计算值=0x%02X, 实际值=0x%02X",
                    calculatedChecksum, actualChecksum));
        }
    }

    /**
     * 解析试验实时数据
     */
    private static DuctilityRealTimeData parseRealTimeData(byte[] data) {
        DuctilityRealTimeData realTimeData = new DuctilityRealTimeData();

        // 数据标志 (第6个字节)
        realTimeData.setFlag(data[5] & 0xFF);

        // 位移量 Length1, Length2, Length3 (2字节无符号，高字节在前)
        realTimeData.setLength1(twoBytesToUnsignedInt(data, 6));
        realTimeData.setLength2(twoBytesToUnsignedInt(data, 8));
        realTimeData.setLength3(twoBytesToUnsignedInt(data, 10));

        // 延伸速率 SPEED (2字节无符号，高字节在前，含1位小数)
        realTimeData.setSpeed(twoBytesToUnsignedInt(data, 12) / 10.0f);

        // 当前温度 CURR_TEMP (2字节有符号，高字节在前，含1位小数)
        realTimeData.setCurrentTemp(twoBytesToSignedInt(data, 14) / 10.0f);

        // 设定温度 SET_TEMP (2字节有符号，高字节在前，含1位小数)
        realTimeData.setSetTemp(twoBytesToSignedInt(data, 16) / 10.0f);

        realTimeData.setDataFlag("0");

        return realTimeData;
    }

    /**
     * 解析试验最终结果
     */
    private static DuctilityFinalResult parseFinalResult(byte[] data) {
        DuctilityFinalResult finalResult = new DuctilityFinalResult();

        // 位移量 Length1, Length2, Length3 (2字节无符号，高字节在前)
        finalResult.setLength1(twoBytesToUnsignedInt(data, 5));
        finalResult.setLength2(twoBytesToUnsignedInt(data, 7));
        finalResult.setLength3(twoBytesToUnsignedInt(data, 9));

        // 延伸速率 SPEED (2字节无符号，高字节在前，含1位小数)
        finalResult.setSpeed(twoBytesToUnsignedInt(data, 11) / 10.0f);

        // 当前温度 CURR_TEMP (2字节有符号，高字节在前，含1位小数)
        finalResult.setCurrentTemp(twoBytesToSignedInt(data, 13) / 10.0f);

        // 设定温度 SET_TEMP (2字节有符号，高字节在前，含1位小数)
        finalResult.setSetTemp(twoBytesToSignedInt(data, 15) / 10.0f);

        finalResult.setDataFlag("1");

        return finalResult;
    }

    /**
     * 将2字节数据转换为无符号整数（高字节在前）
     */
    private static int twoBytesToUnsignedInt(byte[] data, int startIndex) {
        return ((data[startIndex] & 0xFF) << 8) | (data[startIndex + 1] & 0xFF);
    }

    /**
     * 将2字节数据转换为有符号整数（高字节在前）
     */
    private static short twoBytesToSignedInt(byte[] data, int startIndex) {
        return (short) (((data[startIndex] & 0xFF) << 8) | (data[startIndex + 1] & 0xFF));
    }
}
